#include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/types.h>
#include <string.h>

#include "loader.h"
#include "read_word.h"
#include "interpreter.h"
#include "glovars.h"
#include "vm.h"
#include "objects.h"
#include "allocator.h"
#include "builtins.h"
#include "ports.h"

#include <signal.h>

void load_and_exec(char *filename);
void load_qcode_dir();

void stack_and_quit() {
	puts("SIGSEGV");
	stack_trace();
	exit(1);
}

int main(int argc, char **argv) {
	if(argc < 2) {
	        fprintf(stderr, "pass a qcode file to run\n");
		exit(-1);
	}

	int i = 0;
	
	//signal(SIGSEGV, stack_and_quit);

	/// SETUP ARGV
	reg_acc = ATOM_NUL;
	for(i = argc-1; i > 1; i--) {
		// push argv[i] onto the list
		reg_clo = allocate_strg(argv[i], strlen(argv[i]));
		reg_acc = allocate_cons(reg_clo, reg_acc);
	}

	// SETUP STACK
        stack[++reg_rsp] = 0xC0FFEEEEEEEEEEEE;
        stack[++reg_rsp] = SCM_PTR(NULL);
	stack[++reg_rsp] = SCM_PTR(NULL);
	stack[++reg_rsp] = 0;
        stack[++reg_rsp] = 0xDEADBEEFDEADBEEF;
	reg_rbp = reg_rsp;
	
	// SETUP STRUCTURES
	init_port_table();
	builtins_init(reg_acc);

	// LOAD AND EXEC CODE
	load_qcode_dir("/qcode/");
	load_and_exec(argv[1]);
	
	exit(0);
}

void load_and_exec(char *filename)
{
	scm *tmp;
	FILE *code_fptr = fopen(filename, "r");
	
	if(!code_fptr) {
	        fprintf(stderr, "file <%s>\n", filename);
		exit(-1);
	}

	tmp = vm_code + vm_code_size;
	load_code(code_fptr);
	vm_exec(tmp);
}

void load_qcode_dir(char *p)
{
	char buf[256] = { 0 };
	char buf2[256] = { 0 };
	DIR *dir;
	struct dirent *ent;

	if(!getenv("TAROTPATH")) {
		puts("Please set TAROTPATH.");
		exit(2);
	}
	
	strcat(buf, getenv("TAROTPATH"));
	strcat(buf, p);
	dir = opendir(buf);
	if(!dir) {
		printf("Could not open qcode directory <%s%s>. Check TAROTPATH.\n", getenv("TAROTPATH"), p);
		exit(2);
	}
	while((ent = readdir(dir))) {
		if(ent->d_type == DT_REG) {
		        strcpy(buf2, buf);
			strcat(buf2, ent->d_name);
			load_and_exec(buf2);
		}
	}
}
